﻿/**
*    Copyright (C) 2008  Chase Kernan 
*    chase.kernan@gmail.com
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
* 
*/

package com.chasekernan.hxnova.server.functions;

import com.chasekernan.hxnova.core.dataholders.FleetHolder;
import com.chasekernan.hxnova.core.dataholders.Global;
import com.chasekernan.hxnova.core.fleets.Fleet;
import com.chasekernan.hxnova.core.stars.Star;
import com.chasekernan.hxnova.core.dataholders.MessageHandler;
import com.chasekernan.hxnova.server.functions.GroundCombat;

typedef ColonizeOrder = {
    var fleet : Fleet;
    var star : Star;
}

/**
    Runs through the fleets in [Global.fleets] and applies any colonization 
    orders.
**/
class Colonizations {
    
    public static function run() {
        //for locations where multiple races try to colonize the same star.
        var colonizations = new Array < Array < ColonizeOrder >> ();
        for (i in 0...Global.stars.stars.length) colonizations.push(null);
        
        var fleets = new Array<Fleet>();
        for (f in Global.fleets) fleets.push(f);
        
        var i = fleets.length;
        while (i-- > 0) {
            var fleet = fleets[i];
            
            switch(fleet.waypoint0) {
                
                case Colonization:
                    var star = Global.stars.getStarAtLocation(fleet.location);
                    
                    //not orbiting a star
                    if (star == null) {
                        fleet.waypoint0 = Task.NoTask;
                        continue;
                    }
                    
                    //cannot colonize an unoccupied world
                    if (star.owner.id != Global.players.nullPlayer.id) {
                        Global.messages.sendMessage( 
                                {to : Target.PlayerTarget(fleet.owner), 
                                 from : Target.Host, 
                                 data : MessageData.FailedColonization(
                                        fleet.name, star.name)
                        } );
                        fleet.waypoint0 = Task.NoTask;
                        continue;
                    }
                    
                    var order = { fleet : fleet, star : star };
                    if (colonizations[i] == null) colonizations[i] = [order];
                    else colonizations[i].push(order);
                
                default:
                    //do nothing
            }
        }
        
        for (location in colonizations) {
            if (location == null) continue;
            
			//make reference here for easier access
            var star = location[0].star;
            
            //merge fleets from the same player
            for (order in location) {
                for (order2  in location) {
                    if (order == order2) continue;
					
					//this operation is safe because the location array isn't 
					//being modified.
                    if (order.fleet.owner.id == order2.fleet.owner.id) {
                        order.fleet.mergeFleet(order2.fleet);
                    }
                }
            }
            
            //if the location only has one fleet there, then colonization can
            //proceed as normal.
            if (location.length == 1) {
                var order = location[0];
                star.owner = order.fleet.owner;
                star.population = order.fleet.colonists;
               
                var scrap = Scrapping.getScrapFor(order.fleet);
                star.minerals.add(scrap.minerals);
                star.additionalResources += scrap.resources;
                Global.fleets.removeParticle(order.fleet);
               
                Global.messages.sendMessage( { 
                        to : Target.PlayerTarget(order.fleet.owner), 
                        from : Target.Host, 
                        data : MessageData.SuccessfulColonization(star.name)
                });
               
               continue;
            }
            
            //otherwise the fleets have to fight over the star using ground 
            //troops.
            
            //Attacker is defined in GroundCombat
            var combatants = new Array<Attacker>();
            //at the same time, scrap all of the fleets
            for (order in location) {
                var scrap = Scrapping.getScrapFor(order.fleet);
                star.minerals.add(scrap.minerals);
                star.additionalResources += scrap.resources;
                Global.fleets.removeParticle(order.fleet);
                
                combatants.push( { player : order.fleet.owner, 
                                   troops : order.fleet.colonists } );
            }
            
            var winner = GroundCombat.getMultiRaceWinner(combatants, 0);
            
            //if winner is null, the no one won.
            
            //send failed battle messages.
            for (c in combatants) {
                if (winner != null && c.player.id == winner.player.id) {
                    continue;
                }
                    
                Global.messages.sendMessage( { 
                    to : Target.PlayerTarget(c.player), 
                    from : Target.Host, 
                    data : MessageData.FailedColonizationBattle(star.name)
                });
            }
            
            if (winner == null) continue;
            
            star.owner = winner.player;
            star.population = winner.troops;
            
            //successful battle
            Global.messages.sendMessage( { 
                to : Target.PlayerTarget(winner.player), 
                from : Target.Host, 
                data : MessageData.SuccessfulColonizationBattle(star.name)
            });
            //successful colonization
            Global.messages.sendMessage( { 
                to : Target.PlayerTarget(winner.player), 
                from : Target.Host, 
                data : MessageData.SuccessfulColonization(star.name)
            });
        }
    }
    
}